{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true,
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "# Deterministic Inputs, Noisy “And” gate model (DINA)\n",
    "\n",
    "This notebook will show you how to train and use the GDDINA.\n",
    "First, we will show how to get the data (here we use a0910 as the dataset).\n",
    "Then we will show how to train a DINA and perform the parameters persistence.\n",
    "At last, we will show how to load the parameters from the file and evaluate on the test dataset.\n",
    "\n",
    "The script version could be found in [DINA.py](DINA.ipynb)"
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Data Preparation\n",
    "\n",
    "Before we process the data, we need to first acquire the dataset which is shown in [prepare_dataset.ipynb](prepare_dataset.ipynb)"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "outputs": [
    {
     "data": {
      "text/plain": "   user_id  item_id  score                                          knowledge\n0     1615    12977      1  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...\n1      507    12977      0  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...\n2     2724    12977      1  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...\n3     3804    12977      1  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...\n4     3881    12977      0  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>user_id</th>\n      <th>item_id</th>\n      <th>score</th>\n      <th>knowledge</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>1615</td>\n      <td>12977</td>\n      <td>1</td>\n      <td>[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>507</td>\n      <td>12977</td>\n      <td>0</td>\n      <td>[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>2724</td>\n      <td>12977</td>\n      <td>1</td>\n      <td>[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>3804</td>\n      <td>12977</td>\n      <td>1</td>\n      <td>[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>3881</td>\n      <td>12977</td>\n      <td>0</td>\n      <td>[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "\n",
    "train_data = pd.read_csv(\"../../../data/a0910/train.csv\")\n",
    "valid_data = pd.read_csv(\"../../../data/a0910/valid.csv\")\n",
    "test_data = pd.read_csv(\"../../../data/a0910/test.csv\")\n",
    "item_data = pd.read_csv(\"../../../data/a0910/item.csv\")\n",
    "\n",
    "knowledge_num = 123\n",
    "\n",
    "\n",
    "def code2vector(x):\n",
    "    vector = [0] * knowledge_num\n",
    "    for k in eval(x):\n",
    "        vector[k - 1] = 1\n",
    "    return vector\n",
    "\n",
    "\n",
    "item_data[\"knowledge\"] = item_data[\"knowledge_code\"].apply(code2vector)\n",
    "item_data.drop(columns=[\"knowledge_code\"], inplace=True)\n",
    "\n",
    "train_data = pd.merge(train_data, item_data, on=\"item_id\")\n",
    "valid_data = pd.merge(valid_data, item_data, on=\"item_id\")\n",
    "test_data = pd.merge(test_data, item_data, on=\"item_id\")\n",
    "\n",
    "train_data.head(5)\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [
    {
     "data": {
      "text/plain": "(241071, 33131, 71907)"
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(train_data), len(valid_data), len(test_data)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "outputs": [
    {
     "data": {
      "text/plain": "(<torch.utils.data.dataloader.DataLoader at 0x20c1fbdc430>,\n <torch.utils.data.dataloader.DataLoader at 0x20c1fbdf040>,\n <torch.utils.data.dataloader.DataLoader at 0x20c1fbdf700>)"
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Transform data to torch Dataloader (i.e., batchify)\n",
    "# batch_size is set to 256\n",
    "import torch\n",
    "from torch.utils.data import TensorDataset, DataLoader\n",
    "\n",
    "batch_size = 32\n",
    "\n",
    "def transform(x, y, z, k, batch_size, **params):\n",
    "    dataset = TensorDataset(\n",
    "        torch.tensor(x, dtype=torch.int64),\n",
    "        torch.tensor(y, dtype=torch.int64),\n",
    "        torch.tensor(k, dtype=torch.float32),\n",
    "        torch.tensor(z, dtype=torch.float32)\n",
    "    )\n",
    "    return DataLoader(dataset, batch_size=batch_size, **params)\n",
    "\n",
    "\n",
    "train, valid, test = [\n",
    "    transform(data[\"user_id\"], data[\"item_id\"], data[\"score\"], data[\"knowledge\"], batch_size)\n",
    "    for data in [train_data, valid_data, test_data]\n",
    "]\n",
    "train, valid, test\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Training and Persistence"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [],
   "source": [
    "import logging\n",
    "logging.getLogger().setLevel(logging.INFO)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 0: 100%|██████████| 7534/7534 [00:54<00:00, 139.51it/s]\n",
      "evaluating: 100%|██████████| 1036/1036 [00:00<00:00, 1287.18it/s]\n",
      "Epoch 1: 100%|██████████| 7534/7534 [01:02<00:00, 120.28it/s]\n",
      "evaluating: 100%|██████████| 1036/1036 [00:00<00:00, 1318.61it/s]\n",
      "INFO:root:save parameters to dina.params\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Epoch 0] LogisticLoss: 0.705863\n",
      "[Epoch 0] auc: 0.508466, accuracy: 0.495035\n",
      "[Epoch 1] LogisticLoss: 0.702710\n",
      "[Epoch 1] auc: 0.517560, accuracy: 0.504724\n"
     ]
    }
   ],
   "source": [
    "from EduCDM import GDDINA\n",
    "\n",
    "cdm = GDDINA(4164, 17747, knowledge_num)\n",
    "\n",
    "cdm.train(train, valid, epoch=2)\n",
    "cdm.save(\"dina.params\")"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Loading and Testing"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:root:load parameters from dina.params\n",
      "evaluating: 100%|██████████| 2248/2248 [00:01<00:00, 1301.36it/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "auc: 0.523625, accuracy: 0.509630\n"
     ]
    }
   ],
   "source": [
    "cdm.load(\"dina.params\")\n",
    "auc, accuracy = cdm.eval(test)\n",
    "print(\"auc: %.6f, accuracy: %.6f\" % (auc, accuracy))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}